Advanced Usage of Python's Match-Case

Here are concise usage examples for each notable feature of Python's structural pattern matching as introduced in PEP 634 and how its different from traditional switch statement in other languages:

  1. Matching Sequences

    def handle_command(command):
        match command.split():
            case [action, obj]:
                print(f"Action: {action}, Object: {obj}")
            case [action]:
                print(f"Action: {action}")
            case _:
                print("Unknown command")
    
    handle_command("get sword")
    # Output: Action: get, Object: sword
    
  2. Matching Multiple Patterns

    def handle_command(command):
        match command.split():
            case ["look"]:
                print("Looking around")
            case ["go", direction]:
                print(f"Going {direction}")
            case ["pick", obj]:
                print(f"Picking up {obj}")
            case _:
                print("Command not recognized")
    
    handle_command("go north")
    # Output: Going north
    
  3. Matching Specific Values

    def handle_error(status):
        match status:
            case 404:
                return "Not Found"
            case 500:
                return "Server Error"
            case _:
                return "Unknown Error"
    
    print(handle_error(404))
    # Output: Not Found
    
  4. Matching Multiple Values

    def handle_command(command):
        match command.split():
            case ["drop", *items]:
                for item in items:
                    print(f"Dropping {item}")
    
    handle_command("drop key sword cheese")
    # Output: Dropping key
    #         Dropping sword
    #         Dropping cheese
    
  5. Adding a Wildcard

    def handle_command(command):
        match command.split():
            case ["quit"]:
                print("Exiting")
            case _:
                print(f"Unrecognized command: {command}")
    
    handle_command("save game")
    # Output: Unrecognized command: save game
    
  6. Composing Patterns

    def handle_command(command):
        match command.split():
            case ["go", "north"] | ["north"]:
                print("Moving north")
            case ["go", "south"] | ["south"]:
                print("Moving south")
            case _:
                print("Unknown direction")
    
    handle_command("go north")
    # Output: Moving north
    
  7. Capturing Matched Sub-patterns

    def handle_command(command):
        match command.split():
            case ["go", direction as d] if d in ["north", "south", "east", "west"]:
                print(f"Moving {d}")
            case _:
                print("Invalid direction")
    
    handle_command("go east")
    # Output: Moving east
    
  8. Adding Conditions to Patterns (Guards)

    def handle_command(command):
        match command.split():
            case ["go", direction] if direction in ["north", "south", "east", "west"]:
                print(f"Moving {direction}")
            case ["go", _]:
                print("Invalid direction")
            case _:
                print("Command not recognized")
    
    handle_command("go north")
    # Output: Moving north
    
  9. Matching Objects (e.g., Classes)

    class Click:
        def __init__(self, position, button):
            self.position = position
            self.button = button
    
    def handle_event(event):
        match event:
            case Click((x, y), button="left"):
                print(f"Left click at ({x}, {y})")
            case Click((x, y), button="right"):
                print(f"Right click at ({x}, {y})")
            case _:
                print("Unknown event")
    
    event = Click((10, 20), "left")
    handle_event(event)
    # Output: Left click at (10, 20)
    
  10. Matching Positional Attributes

    from dataclasses import dataclass
    
    @dataclass
    class Point:
        x: int
        y: int
    
    def handle_point(point):
        match point:
            case Point(x=0, y=0):
                print("Origin")
            case Point(x=0, y=y):
                print(f"On the y-axis at {y}")
            case Point(x=x, y=0):
                print(f"On the x-axis at {x}")
            case Point(x, y):
                print(f"Point at ({x}, {y})")
    
    p = Point(0, 10)
    handle_point(p)
    # Output: On the y-axis at 10
    
  11. Matching Against Constants and Enums

    from enum import Enum
    
    class Color(Enum):
        RED = 1
        GREEN = 2
        BLUE = 3
    
    def handle_color(color):
        match color:
            case Color.RED:
                print("Red color")
            case Color.GREEN:
                print("Green color")
            case Color.BLUE:
                print("Blue color")
            case _:
                print("Unknown color")
    
    handle_color(Color.GREEN)
    # Output: Green color
    
  12. Matching Mappings

    def handle_action(action):
        match action:
            case {"text": message, "color": color}:
                print(f"Text: {message}, Color: {color}")
            case {"sleep": duration}:
                print(f"Sleeping for {duration} seconds")
            case _:
                print("Unknown action")
    
    handle_action({"text": "Hello", "color": "blue"})
    # Output: Text: Hello, Color: blue